using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using KnowledgeQA.Core.Interfaces;
using System.Text;
using System.Text.Json;

namespace KnowledgeQA.Core.Implementations
{
    /// <summary>
    /// OpenAI服务实现类
    /// </summary>
    public class OpenAIService : IAIService
    {
        private readonly ILogger<OpenAIService> _logger;
        private readonly IConfiguration _configuration;
        private readonly HttpClient _httpClient;
        private readonly string _apiKey;
        private readonly string _baseUrl;
        private readonly string _model;
        private readonly string _embeddingModel;

        public OpenAIService(ILogger<OpenAIService> logger, IConfiguration configuration)
        {
            _logger = logger;
            _configuration = configuration;
            _httpClient = new HttpClient();
            
            // 从配置中获取API设置
            _apiKey = _configuration["OpenAI:ApiKey"] ?? "your-api-key-here";
            _baseUrl = _configuration["OpenAI:BaseUrl"] ?? "https://api.openai.com/v1";
            _model = _configuration["OpenAI:Model"] ?? "gpt-3.5-turbo";
            _embeddingModel = _configuration["OpenAI:EmbeddingModel"] ?? "nomic-embed-text:latest";
            
            // 设置默认请求头
            _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}");
        }

        public string ModelName => _model;

        public async Task<AIResponse> GenerateAnswerAsync(string prompt, string? context = null, Dictionary<string, object>? parameters = null)
        {
            try
            {
                var stopwatch = System.Diagnostics.Stopwatch.StartNew();
                _logger.LogInformation("开始生成AI回答，模型: {Model}", _model);

                // 构建完整的提示词
                var fullPrompt = BuildFullPrompt(prompt, context);
                
                // 构建请求体
                var requestBody = new
                {
                    model = _model,
                    messages = new[]
                    {
                        new { role = "system", content = "你是一个专业的知识库问答助手。请基于提供的文档内容回答用户的问题。" },
                        new { role = "user", content = fullPrompt }
                    },
                    max_tokens = GetParameterValue(parameters, "maxTokens", 2000),
                    temperature = GetParameterValue(parameters, "temperature", 0.7),
                    top_p = GetParameterValue(parameters, "topP", 1.0),
                    frequency_penalty = GetParameterValue(parameters, "frequencyPenalty", 0.0),
                    presence_penalty = GetParameterValue(parameters, "presencePenalty", 0.0)
                };

                var json = JsonSerializer.Serialize(requestBody);
                var content = new StringContent(json, Encoding.UTF8, "application/json");

                // 发送请求
                var response = await _httpClient.PostAsync($"{_baseUrl}/chat/completions", content);
                
                if (!response.IsSuccessStatusCode)
                {
                    var errorContent = await response.Content.ReadAsStringAsync();
                    _logger.LogError("OpenAI API调用失败，状态码: {StatusCode}, 错误: {Error}", response.StatusCode, errorContent);
                    
                    return new AIResponse
                    {
                        Success = false,
                        ErrorMessage = $"API调用失败: {response.StatusCode} - {errorContent}"
                    };
                }

                var responseContent = await response.Content.ReadAsStringAsync();
                var responseData = JsonSerializer.Deserialize<OpenAIResponse>(responseContent);

                if (responseData?.choices?.Length > 0)
                {
                    var choice = responseData.choices[0];
                    var aiResponse = new AIResponse
                    {
                        Success = true,
                        Content = choice.message?.content ?? "无回答内容",
                        TokensUsed = responseData.usage?.total_tokens ?? 0,
                        ProcessingTime = stopwatch.ElapsedMilliseconds,
                        ConfidenceScore = CalculateConfidenceScore(choice)
                    };

                    stopwatch.Stop();
                    aiResponse.ProcessingTime = stopwatch.ElapsedMilliseconds;

                    _logger.LogInformation("AI回答生成完成，令牌数: {Tokens}, 处理时间: {ProcessingTime}ms", 
                        aiResponse.TokensUsed, aiResponse.ProcessingTime);

                    return aiResponse;
                }
                else
                {
                    return new AIResponse
                    {
                        Success = false,
                        ErrorMessage = "API响应格式错误"
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "生成回答失败");
                return new AIResponse
                {
                    Success = false,
                    ErrorMessage = ex.Message
                };
            }
        }

        public async Task<float[]> GenerateEmbeddingAsync(string text)
        {
            try
            {
                _logger.LogInformation("开始生成向量嵌入，文本长度: {Length}", text.Length);

                // 构建请求体
                var requestBody = new
                {
                    model = $"{_embeddingModel}", // 使用标准的嵌入模型
                    input = text
                };

                var json = JsonSerializer.Serialize(requestBody);
                var content = new StringContent(json, Encoding.UTF8, "application/json");

                // 发送请求
                var response = await _httpClient.PostAsync($"{_baseUrl}/embeddings", content);
                
                if (!response.IsSuccessStatusCode)
                {
                    var errorContent = await response.Content.ReadAsStringAsync();
                    _logger.LogError("OpenAI Embedding API调用失败，状态码: {StatusCode}, 错误: {Error}", 
                        response.StatusCode, errorContent);
                    
                    // 如果API调用失败，返回随机向量作为备用
                    return GenerateRandomEmbedding(1536);
                }

                var responseContent = await response.Content.ReadAsStringAsync();
                var responseData = JsonSerializer.Deserialize<OpenAIEmbeddingResponse>(responseContent);

                if (responseData?.data?.Length > 0)
                {
                    var embedding = responseData.data[0].embedding;
                    var floatArray = embedding.Select(x => (float)x).ToArray();
                    
                    _logger.LogInformation("向量嵌入生成完成，维度: {Dimension}", floatArray.Length);
                    return floatArray;
                }
                else
                {
                    _logger.LogWarning("Embedding API响应格式错误，使用随机向量");
                    return GenerateRandomEmbedding(1536);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "生成向量嵌入失败，使用随机向量");
                return GenerateRandomEmbedding(1536);
            }
        }

        public async Task<float[][]> GenerateEmbeddingsAsync(IEnumerable<string> texts)
        {
            try
            {
                var embeddings = new List<float[]>();
                foreach (var text in texts)
                {
                    var embedding = await GenerateEmbeddingAsync(text);
                    embeddings.Add(embedding);
                }

                return embeddings.ToArray();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量生成向量嵌入失败");
                throw;
            }
        }

        public async Task<double> CalculateSimilarityAsync(string text1, string text2)
        {
            try
            {
                var embedding1 = await GenerateEmbeddingAsync(text1);
                var embedding2 = await GenerateEmbeddingAsync(text2);

                // 计算余弦相似度
                var dotProduct = 0.0f;
                var norm1 = 0.0f;
                var norm2 = 0.0f;

                for (int i = 0; i < embedding1.Length; i++)
                {
                    dotProduct += embedding1[i] * embedding2[i];
                    norm1 += embedding1[i] * embedding1[i];
                    norm2 += embedding2[i] * embedding2[i];
                }

                norm1 = (float)Math.Sqrt(norm1);
                norm2 = (float)Math.Sqrt(norm2);

                if (norm1 == 0 || norm2 == 0)
                {
                    return 0;
                }

                return dotProduct / (norm1 * norm2);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "计算文本相似度失败");
                throw;
            }
        }

        public async Task<bool> IsAvailableAsync()
        {
            try
            {
                // 尝试调用一个简单的API来检查服务可用性
                var response = await _httpClient.GetAsync($"{_baseUrl}/models");
                return response.IsSuccessStatusCode;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查服务可用性失败");
                return false;
            }
        }

        private string BuildFullPrompt(string prompt, string? context)
        {
            var fullPrompt = new StringBuilder();
            
            if (!string.IsNullOrEmpty(context))
            {
                fullPrompt.AppendLine("相关文档内容：");
                fullPrompt.AppendLine(context);
                fullPrompt.AppendLine();
            }
            
            fullPrompt.AppendLine("用户问题：");
            fullPrompt.AppendLine(prompt);
            
            return fullPrompt.ToString();
        }

        private T GetParameterValue<T>(Dictionary<string, object>? parameters, string key, T defaultValue)
        {
            if (parameters != null && parameters.TryGetValue(key, out var value))
            {
                try
                {
                    return (T)Convert.ChangeType(value, typeof(T));
                }
                catch
                {
                    return defaultValue;
                }
            }
            return defaultValue;
        }

        private double CalculateConfidenceScore(OpenAIChoice choice)
        {
            // 基于finish_reason和内容长度计算置信度
            var baseScore = 0.8;
            
            if (choice.finish_reason == "stop")
            {
                baseScore += 0.1;
            }
            
            if (!string.IsNullOrEmpty(choice.message?.content))
            {
                var contentLength = choice.message.content.Length;
                if (contentLength > 50)
                {
                    baseScore += 0.05;
                }
                if (contentLength > 100)
                {
                    baseScore += 0.05;
                }
            }
            
            return Math.Min(baseScore, 1.0);
        }

        private float[] GenerateRandomEmbedding(int dimension)
        {
            var random = new Random();
            var embedding = new float[dimension];
            for (int i = 0; i < embedding.Length; i++)
            {
                embedding[i] = (float)(random.NextDouble() * 2 - 1);
            }
            return embedding;
        }

        // OpenAI API响应模型
        private class OpenAIResponse
        {
            public OpenAIChoice[]? choices { get; set; }
            public OpenAIUsage? usage { get; set; }
        }

        private class OpenAIChoice
        {
            public OpenAIMessage? message { get; set; }
            public string? finish_reason { get; set; }
        }

        private class OpenAIMessage
        {
            public string? content { get; set; }
        }

        private class OpenAIUsage
        {
            public int total_tokens { get; set; }
        }

        private class OpenAIEmbeddingResponse
        {
            public OpenAIEmbeddingData[]? data { get; set; }
        }

        private class OpenAIEmbeddingData
        {
            public double[]? embedding { get; set; }
        }
    }
} 